package com.github.doobo.sm2;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;

import java.io.ByteArrayInputStream;
import java.security.PrivateKey;
import java.security.PublicKey;

/**
 * 接口功能描述
 *
 * @Description: sm2
 * @User: diding
 * @Time: 2021-08-30 17:30
 */
public class Sm2Main {

    public static void main(String[] args) {

        Sm2Main main = new Sm2Main();
        main.createKeys();
        System.out.println();
        main.decodeSm2();
    }

    /**
     * 生成密钥对
     */
    public void createKeys(){
        SM2 sm2 = SmUtil.sm2();
        String privateKey = HexUtil.encodeHexStr(sm2.getPrivateKey().getEncoded());
        String publicKey = HexUtil.encodeHexStr(sm2.getPublicKey().getEncoded());
        System.out.println("private:" + privateKey);
        System.out.println("public:" + publicKey);
        System.out.println();

        //JS端兼容,q值作为JS端加密公钥,d值作为私钥
        //((BCECPrivateKey) privateKey).getD().toByteArray();
        privateKey = HexUtil.encodeHexStr(((BCECPrivateKey) sm2.getPrivateKey()).getD().toByteArray());
        String tmp =  HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        System.out.println("private:" + privateKey);
        System.out.println("private-tmp:" + tmp);

        //((BCECPublicKey) publicKey).getQ().getEncoded(true)
        publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
        tmp = HexUtil.encodeHexStr(BCUtil.encodeECPublicKey(sm2.getPublicKey()));
        System.out.println("publicKey:" + publicKey);
        System.out.println("publicKey-tmp:" + tmp);
    }

    public void decodeSm2(){
        String q = "0441766bc0ac159b3db852f848f52c23084cab493d1dfa8f14d06ee6ddbeda600406763c7f0c2f9bd6d6ca3b87f13bbf22dfcfc4e9ecc10999feeace3a8a6a94c3";
        PublicKey v1 = BCUtil.decodeECPoint(q, "sm2p256v1");
        SM2 sm2 = SmUtil.sm2();
        sm2.setPublicKey(v1);
        //加密
        String myDate = sm2.encryptHex("admin", KeyType.PublicKey);
        System.out.println(myDate);
        //解密
        String d = "241feeba871c517d21ef535d0efb2a21528b3e93b3a3bb010af3a13bf479565a";
        ECPrivateKeyParameters privateKeyParameters = BCUtil.toSm2Params(d);
        sm2 = new SM2(privateKeyParameters, null);
        sm2.usePlainEncoding();
        myDate = sm2.decryptStr(myDate, KeyType.PrivateKey);
        System.out.println(myDate);
        //加密方法二
        if (q.length() == 130) {
            //这里需要去掉开始第一个字节 第一个字节表示未压缩标记
            q = q.substring(2);
        }
        String xhex = q.substring(0, 64);
        String yhex = q.substring(64, 128);
        ECPublicKeyParameters publicKeyParameters = BCUtil.toSm2Params(xhex, yhex);
        sm2 = new SM2(null, publicKeyParameters);
        sm2.usePlainEncoding();
        myDate = sm2.encryptHex("admin", KeyType.PublicKey);
        System.out.println(myDate);
    }
}
